package com.san.metadata.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.san.base.controller.BaseController;
import com.san.common.annotation.Log;
import com.san.common.datasource.JdbcEntity;
import com.san.common.datasource.JdbcManager;
import com.san.common.utils.AESUtils;
import com.san.common.utils.Constant;
import com.san.common.utils.PageUtils;
import com.san.common.utils.Query;
import com.san.common.utils.R;
import com.san.metadata.domain.DataSourceDO;
import com.san.metadata.service.DataSourceService;
import com.san.metadata.vo.DataSourceVO;

/**
 * 数据源管理业务控制器
 * 
 * @author xiangyz
 *
 */
@RequestMapping("/md/source")
@Controller
public class DataSourceController extends BaseController {

	private static final Logger logger = LoggerFactory.getLogger(DataSourceController.class);

	/**
	 * 本功能地址前缀
	 */
	private static final String PREFIX = "metadata/source";

	@Autowired
	DataSourceService dataSourceService;

	/**
	 * 数据源列表页
	 * 
	 * @param model
	 * @return
	 */
	@RequiresPermissions("md:source:view")
	@GetMapping("")
	String source(Model model) {
		return PREFIX + "/view";
	}

	/**
	 * 数据源列表接口
	 * 
	 * @param params
	 * @return
	 */
	@GetMapping("/list")
	@ResponseBody
	public PageUtils findListSource(@RequestParam Map<String, Object> params) {
		PageUtils pageUtils = null;
		try {
			Query query = new Query(params);
			pageUtils = dataSourceService.findListSource(query);
		} catch (Exception e) {
			logger.error("分页获取数据源列表出错", e);
		}

		return pageUtils;
	}

	/**
	 * 数据源列表接口
	 * 
	 * @param params
	 * @return
	 */
	@GetMapping("/getAllSource")
	@ResponseBody
	public List<DataSourceDO> getAllSource() {
		List<DataSourceDO> list = null;
		try {
			list = dataSourceService.getAllSource();
		} catch (Exception e) {
			logger.error("获取数据源列表出错", e);
		}

		return list;
	}

	@GetMapping("/add")
	@Log("新增数据源")
	@RequiresPermissions("md:source:add")
	String add() {
		return PREFIX + "/add";
	}

	@ResponseBody
	@Log("数据源连接测试")
	@PostMapping("/connTest")
	public R connTest(DataSourceVO dataSourceVO) {

		try {
			if (dataSourceVO.getSourceId() > 0) {
				DataSourceDO dataSourceDO = (DataSourceDO) dataSourceService.getById(dataSourceVO.getSourceId());
				// 前端传入密码
				String viewPassword = dataSourceVO.getDbPassword();
				// 数据库存入密码
				String dbPassword = dataSourceDO.getDbPassword();

				if (null != viewPassword && viewPassword.equals(dbPassword)) {
					// 前端密码与数据加密密码一致，判定为未修改，需进行解密操作
					dataSourceVO.setDbPassword(AESUtils.AESDecode(Constant.DATA_SOURCE_KEY, viewPassword));
				}
			}
		} catch (Exception e) {
			logger.info("连接测试出错", e);
		}

		JdbcManager jdbcManager = new JdbcManager();

		if (jdbcManager.testConnection(this.buildJdbcEntity(dataSourceVO))) {
			return R.ok("测试连接成功");
		} else {
			return R.error(1, "测试连接失败");
		}
	}

	/**
	 * 构建JDBC连接属性
	 * 
	 * @param dataSourceVO
	 * @return
	 */
	public JdbcEntity buildJdbcEntity(DataSourceVO dataSourceVO) {
		JdbcEntity entity = new JdbcEntity();
		entity.setSourceType(dataSourceVO.getSourceType());
		entity.setIp(dataSourceVO.getIpAddress());
		entity.setPort(dataSourceVO.getPort());
		entity.setDbName(dataSourceVO.getDbName());
		entity.setUser(dataSourceVO.getDbUser());
		entity.setPassword(dataSourceVO.getDbPassword());

		return entity;
	}

	@ResponseBody
	@Log("保存数据源")
	@PostMapping("/save")
	public R save(DataSourceVO dataSourceVO) {
		dataSourceVO.setCreateUserId(getUserId());
		dataSourceVO.setStatus(Constant.STATUS_INVALID);
		dataSourceVO.setSourceCode(dataSourceVO.getSourceCode().toUpperCase());
		try {
			boolean bool = this.checkExistsSourceCode(dataSourceVO);
			if (bool) {
				return R.error("数据源编码已存在");
			}

			// 连接测试
			JdbcManager jdbcManager = new JdbcManager();

			if (jdbcManager.testConnection(this.buildJdbcEntity(dataSourceVO))) {
				dataSourceVO.setStatus(Constant.STATUS_NORMAL);
			}

			// 加密
			dataSourceVO.setDbPassword(AESUtils.AESEncode(Constant.DATA_SOURCE_KEY, dataSourceVO.getDbPassword()));
			if (dataSourceService.save(dataSourceVO) > 0) {
				return R.ok();
			}
		} catch (Exception e) {
			logger.error("保存数据源出错", e);
			return R.error();
		}
		return R.error();
	}

	@RequiresPermissions("md:source:edit")
	@Log("编辑数据源")
	@GetMapping("/edit/{id}")
	String edit(Model model, @PathVariable("id") Long id) {
		try {
			DataSourceDO dataSourceDO = (DataSourceDO) dataSourceService.getById(id);
			model.addAttribute("source", dataSourceDO);
		} catch (Exception e) {
			logger.error("获取数据源信息出错", e);
		}

		return PREFIX + "/edit";
	}

	@RequiresPermissions("md:source:edit")
	@Log("更新数据源")
	@PostMapping("/doEdit")
	@ResponseBody
	R doEdit(DataSourceVO dataSourceVO) {
		dataSourceVO.setSourceCode(dataSourceVO.getSourceCode().toUpperCase());
		try {

			// 校验名称重复
			boolean bool = this.checkExistsSourceCode(dataSourceVO);
			if (bool) {
				return R.error("数据源编码已存在");
			}

			DataSourceDO dataSourceDO = (DataSourceDO) dataSourceService.getById(dataSourceVO.getSourceId());

			// 前端传入密码
			String viewPassword = dataSourceVO.getDbPassword();
			// 数据库存入
			String dbPassword = dataSourceDO.getDbPassword();

			if (null != viewPassword && viewPassword.equals(dbPassword)) {
				// 前端密码与数据加密密码一致，判定为未修改，需进行解密操作
				dataSourceVO.setDbPassword(AESUtils.AESDecode(Constant.DATA_SOURCE_KEY, viewPassword));
			}

			// 连接测试
			JdbcManager jdbcManager = new JdbcManager();

			if (jdbcManager.testConnection(this.buildJdbcEntity(dataSourceVO))) {
				dataSourceVO.setStatus(Constant.STATUS_NORMAL);
			} else {
				dataSourceVO.setStatus(Constant.STATUS_INVALID);
			}

			// 修改操作人员
			dataSourceVO.setUpdateUserId(getUserId());

			// 加密
			dataSourceVO.setDbPassword(AESUtils.AESEncode(Constant.DATA_SOURCE_KEY, dataSourceVO.getDbPassword()));
			if (dataSourceService.doEdit(dataSourceVO) > 0) {
				return R.ok();
			}
		} catch (Exception e) {
			logger.error("更新数据源出错", e);
			return R.error();
		}
		return R.error();
	}

	@RequiresPermissions("md:source:remove")
	@Log("删除数据源")
	@PostMapping("/remove")
	@ResponseBody
	R remove(Long id) {
		try {
			if (dataSourceService.remove(id) > 0) {
				return R.ok();
			}
		} catch (Exception e) {
			logger.error("删除数据源出错", e);
		}
		return R.error();
	}

	@RequiresPermissions("md:source:batchRemove")
	@Log("批量删除数据源")
	@PostMapping("/batchRemove")
	@ResponseBody
	R batchRemove(@RequestParam("ids[]") Long[] ids) {
		try {
			int r = dataSourceService.batchRemove(ids);
			if (r > 0) {
				return R.ok();
			}
		} catch (Exception e) {
			logger.error("批量删除数据源出错", e);
		}

		return R.error();
	}

	public boolean checkExistsSourceCode(DataSourceVO dataSourceVO) throws Exception {
		boolean result = false;

		// 构建查询条件
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("sourceCode", dataSourceVO.getSourceCode());
		Query query = new Query(params);

		List<DataSourceDO> list = dataSourceService.findSource(query);
		if (null != list && list.size() > 0) {
			// 修改
			if (dataSourceVO.getSourceId() > 0) {
				for (DataSourceDO dataSourceDO : list) {
					// 名称相同，ID不同，重复
					if (dataSourceDO.getSourceId() != dataSourceVO.getSourceId()) {
						result = true;
						break;
					}
				}
			} else {
				result = true;
			}
		}
		return result;
	}
}
